package com.itcoon.cloud.framework.security.config;/**
 * @author Athric Yu
 * 2025/1/3
 **/

import com.itcoon.cloud.framework.ex.config.ExRegistryConfigurer;
import com.itcoon.cloud.framework.ex.register.IErrorCodeRegister;
import com.itcoon.cloud.framework.security.config.properties.AuthEntrypointManageProperties;
import com.itcoon.cloud.framework.security.config.properties.JwtTokenProperties;
import com.itcoon.cloud.framework.security.ex.SecurityResponseEnum;
import com.itcoon.cloud.framework.security.filter.SwaggerApiKeyAuthFilter;
import com.itcoon.cloud.framework.security.filter.SwaggerBasicAuthFilter;
import com.itcoon.cloud.framework.security.handler.DefaultAccessDeniedHandler;
import com.itcoon.cloud.framework.security.handler.DefaultAuthenticationEntryPoint;
import com.itcoon.cloud.framework.security.handler.DefaultAuthenticationFailureHandler;
import com.itcoon.cloud.framework.security.handler.DefaultLogoutSuccessHandler;
import com.itcoon.cloud.framework.security.provider.DaoAuthenticationProvider;
import com.itcoon.cloud.framework.security.web.controller.AuthController;
import com.itcoon.cloud.framework.utils.SpringUtils;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

/**
 *
 *
 * @author Athric Yu
 * 2025/1/3
 **/
@AutoConfiguration
@EnableConfigurationProperties({AuthEntrypointManageProperties.class, JwtTokenProperties.class})
public class SecurityBeanAutoConfiguration implements ExRegistryConfigurer {

    @Bean
    @ConditionalOnMissingBean(PasswordEncoder.class)
    public PasswordEncoder passwordEncoder() {
        DelegatingPasswordEncoder passwordEncoder = (DelegatingPasswordEncoder) PasswordEncoderFactories.createDelegatingPasswordEncoder();
        passwordEncoder.setDefaultPasswordEncoderForMatches(new BCryptPasswordEncoder(BCryptPasswordEncoder.BCryptVersion.$2B));
        return passwordEncoder;
    }

    @Bean
    @ConditionalOnMissingBean(AccessDeniedHandler.class)
    public DefaultAccessDeniedHandler defaultAccessDeniedHandler(IErrorCodeRegister errorCodeRegister){
        return new DefaultAccessDeniedHandler(errorCodeRegister);
    }

    @Bean
    @ConditionalOnMissingBean(AuthenticationEntryPoint.class)
    public DefaultAuthenticationEntryPoint defaultAuthenticationEntryPoint(IErrorCodeRegister errorCodeRegister){
        return new DefaultAuthenticationEntryPoint(errorCodeRegister);
    }

    @Bean
    @ConditionalOnMissingBean(AuthenticationFailureHandler.class)
    public DefaultAuthenticationFailureHandler defaultAuthenticationFailureHandler(IErrorCodeRegister errorCodeRegister){
        return new DefaultAuthenticationFailureHandler(errorCodeRegister);
    }

    @Bean
    @ConditionalOnMissingBean(LogoutSuccessHandler.class)
    public DefaultLogoutSuccessHandler jsonLogoutSuccessHandler(){
        return new DefaultLogoutSuccessHandler();
    }


    @Bean
    @ConditionalOnMissingBean(AuthenticationProvider.class)
    public DaoAuthenticationProvider daoAuthenticationProvider(PasswordEncoder passwordEncoder, UserDetailsService userDetailsService){
        return new DaoAuthenticationProvider(passwordEncoder, userDetailsService);
    }

    @Bean
    @ConditionalOnProperty(prefix="springdoc.swagger-ui", name = "enabled", havingValue="true")
    public SwaggerBasicAuthFilter swaggerBasicAuthFilter(AuthenticationProvider authenticationProvider, AuthenticationEntryPoint authenticationEntryPoint, JwtTokenProperties jwtTokenProperties){
        return new SwaggerBasicAuthFilter(authenticationProvider, authenticationEntryPoint, jwtTokenProperties);
    }

    @Bean
    @ConditionalOnProperty(prefix="springdoc.swagger-ui", name = "enabled", havingValue="true")
    public SwaggerApiKeyAuthFilter swaggerApiKeyAuthFilter(JwtTokenProperties jwtTokenProperties){
        return new SwaggerApiKeyAuthFilter(jwtTokenProperties);
    }

    @Override
    public void registerErrorCodes(IErrorCodeRegister register) {
        register.register(SpringUtils.getApplicationName(), SecurityResponseEnum.class);
    }

    @Bean
    public AuthController authController(){
        return new AuthController();
    }
}
